﻿using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace BuildExplorer
{
    [CLSCompliant(false)]  // We use P/Invoke with non-CLS-compliant types
    public static class RichTextBoxExtensions
    {
        [DllImport("user32.dll")]
        private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
        private const int WM_SETREDRAW = 0x0b;

        public static void BeginUpdate(this RichTextBox r)
        {
            SendMessage(r.Handle, WM_SETREDRAW, (IntPtr)0, IntPtr.Zero);
        }

        public static void EndUpdate(this RichTextBox r)
        {
            SendMessage(r.Handle, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero);
            r.Invalidate();
        }

        private const int PFM_SPACEAFTER = 128;
        private const int PFM_LINESPACING = 256;
        private const int EM_SETPARAFORMAT = 1095;

        [StructLayout(LayoutKind.Sequential)]
        public struct PARAFORMAT2
        {
            public int cbSize;
            public uint dwMask;
            public short wNumbering;
            public short wReserved;
            public int dxStartIndent;
            public int dxRightIndent;
            public int dxOffset;
            public short wAlignment;
            public short cTabCount;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
            public int[] rgxTabs;

            // PARAFORMAT2
            public int dySpaceBefore;
            public int dySpaceAfter;
            public int dyLineSpacing; // in twips
            public short sStyle;
            public byte bLineSpacingRule;
            public byte bOutlineLevel;
            public short wShadingWeight;
            public short wShadingStyle;
            public short wNumberingStart;
            public short wNumberingStyle;
            public short wNumberingTab;
            public short wBorderSpace;
            public short wBorderWidth;
            public short wBorders;
        }

        [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
        public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, ref PARAFORMAT2 lParam);

        public static void SetSelectionSpaceAfter(this RichTextBox r, int spaceAfter)
        {
            PARAFORMAT2 fmt = new PARAFORMAT2();
            fmt.cbSize = Marshal.SizeOf(fmt);

            fmt.dwMask |= PFM_LINESPACING | PFM_SPACEAFTER;
            fmt.dySpaceAfter = spaceAfter;  // in twips = "twentieth of a point"
            fmt.bLineSpacingRule = Convert.ToByte(0); // 0 - single spacing, with SpaceAfter taking effect

            SendMessage(r.Handle, EM_SETPARAFORMAT, 1, ref fmt); // 0 - to all text. 1 - only to seleted
        }
    }
}
